package com.damai.exception;

import com.damai.common.ApiResponse;
import com.damai.enums.BaseCode;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@RestControllerAdvice
public class DefaultExceptionHandler {

    /**
     * 业务异常
     */
    @ExceptionHandler(value = DaMaiFrameException.class)
    public ApiResponse<String> toolkitExceptionHandler(HttpServletRequest request, DaMaiFrameException damaiFrameException) {
        log.error("业务异常 method:{}, url:{}, query:{}", request.getMethod(), getRequestUrl(request), getRequestQuery(request), damaiFrameException);
        return ApiResponse.error(damaiFrameException.getCode(), damaiFrameException.getMessage());
    }

    /**
     * 参数验证异常
     * 客户端发送请求，其携带的数据未能满足服务端预设的规则或约束时抛出的异常
     * 例如数据类型不匹配，期望一个整数但收到了一个字符串
     * 例如某个必填字段没有提供值
     */
    @SneakyThrows   //无需显式写出try-catch块，允许方法抛出检查型异常，例如IOException
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public ApiResponse<List<ArgumentError>> validExceptionHandler(HttpServletRequest request, MethodArgumentNotValidException ex) {
        log.error("参数验证异常 method:{}, url:{}, query:{}", request.getMethod(), getRequestUrl(request), getRequestQuery(request), ex);
        BindingResult bindingResult = ex.getBindingResult();
        List<ArgumentError> argumentErrorList = bindingResult.getFieldErrors().stream()  //获取字段错误列表
                .map(fieldError -> {
                    ArgumentError argumentError = new ArgumentError();
                    argumentError.setArgumentName(fieldError.getField());
                    argumentError.setMessage(fieldError.getDefaultMessage());
                    return argumentError;
                }).collect(Collectors.toList());
        return ApiResponse.error(BaseCode.PARAMETER_ERROR.getCode(), argumentErrorList);
    }

    private String getRequestUrl(HttpServletRequest request) {
        return request.getRequestURL().toString();
    }

    private String getRequestQuery(HttpServletRequest request) {
        return request.getQueryString();  //只能获取GET请求的参数
    }

}
